home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / bootp / RCS / bootp.c,v < prev    next >
Encoding:
Text File  |  1990-11-13  |  19.5 KB  |  979 lines

  1. head     1.7;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    shirriff:1.7; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.7
  10. date     90.11.06.17.20.04;  author jhh;  state Exp;
  11. branches ;
  12. next     1.6;
  13.  
  14. 1.6
  15. date     90.11.06.16.46.25;  author shirriff;  state Exp;
  16. branches ;
  17. next     1.5;
  18.  
  19. 1.5
  20. date     90.03.29.14.53.03;  author brent;  state Exp;
  21. branches ;
  22. next     1.4;
  23.  
  24. 1.4
  25. date     90.01.25.17.50.58;  author shirriff;  state Exp;
  26. branches ;
  27. next     1.3;
  28.  
  29. 1.3
  30. date     89.11.16.02.11.39;  author rab;  state Exp;
  31. branches ;
  32. next     1.2;
  33.  
  34. 1.2
  35. date     89.08.22.10.01.31;  author nelson;  state Exp;
  36. branches ;
  37. next     1.1;
  38.  
  39. 1.1
  40. date     89.07.20.16.15.32;  author nelson;  state Exp;
  41. branches ;
  42. next     ;
  43.  
  44.  
  45. desc
  46. @@
  47.  
  48.  
  49. 1.7
  50. log
  51. @added ds5000 support
  52. @
  53. text
  54. @/*
  55.  * bootp.c --
  56.  *
  57.  */
  58.  
  59. #ifndef lint
  60. static char sccsid[] = "@@(#)bootp.c    1.1 (Stanford) 1/22/86";
  61. #endif
  62.  
  63. /*
  64.  * BOOTP (bootstrap protocol) server daemon.
  65.  *
  66.  * Answers BOOTP request packets from booting client machines.
  67.  * See [SRI-NIC]<RFC>RFC951.TXT for a description of the protocol.
  68.  */
  69.  
  70. /*
  71.  * history
  72.  * 01/22/86    Croft    created.
  73.  */
  74.  
  75. #include <sys/types.h>
  76. #include <sys/stat.h>
  77. #include <sys/socket.h>
  78. #include <sys/ioctl.h>
  79. #include <sys/file.h>
  80.  
  81. #include <net/if.h>
  82. #include <netinet/in.h>
  83. #define    iaddr_t struct in_addr
  84. #include "bootp.h"
  85.  
  86. #include <signal.h>
  87. #include <stdio.h>
  88. #include <strings.h>
  89. #include <errno.h>
  90. #include <ctype.h>
  91. #include <netdb.h>
  92. #include <setjmp.h>
  93. #include <varargs.h>
  94. #include <time.h>
  95.  
  96. static int    debug;
  97. extern    int errno;
  98. static struct    sockaddr_in sin = { AF_INET };
  99. static int    s;        /* socket fd */
  100. static struct    sockaddr_in from;
  101. static int    fromlen;
  102. static u_char    buf[1024];    /* receive packet buffer */
  103. extern long    time();            /* time of day */
  104. static struct    ifreq ifreq[10]; /* holds interface configuration */
  105. static struct    ifconf ifconf;    /* int. config. ioctl block (points to ifreq) */
  106. static struct    arpreq arpreq;    /* arp request ioctl block */
  107.  
  108. /*
  109.  * Globals below are associated with the bootp database file (bootptab).
  110.  */
  111.  
  112. static char    *bootptab = "/etc/spritehosts";
  113. static char    *bootplog = "/sprite/admin/bootplog";
  114. static FILE    *fp;
  115. static int    f;
  116. static char    line[256];    /* line buffer for reading bootptab */
  117. static char    *linep;        /* pointer to 'line' */
  118. static int    linenum;    /* current ilne number in bootptab */
  119.  
  120. /* bootfile homedirectory */
  121. static char    homedir[] = "/sprite/boot";
  122. static char    defaultboot[] = "ds3100"; /* default file to boot */
  123.  
  124. #define    MHOSTS    512    /* max number of 'hosts' structs */
  125.  
  126. static struct hosts {
  127.     char    host[31];    /* host name (and suffix) */
  128.     u_char    htype;        /* hardware type */
  129.     u_char    haddr[6];    /* hardware address */
  130.     iaddr_t    iaddr;        /* internet address */
  131.     char    bootfile[32];    /* default boot file name */
  132. } hosts[MHOSTS];
  133.  
  134. static int    nhosts;        /* current number of hosts */
  135. static long    modtime;    /* last modification time of bootptab */
  136.  
  137. static struct in_addr myAddr;
  138.  
  139. static void log();
  140. static void request();
  141. static void reply();
  142. static void sendreply();
  143. static int nmatch();
  144. static void setarp();
  145. static void getfield();
  146. static void readtab();
  147.  
  148. void
  149. main(argc, argv)
  150.     char *argv[];
  151. {
  152.     register struct bootp *bp;
  153.     register int n;
  154.     char hostname[100];
  155.     struct hostent *hostentPtr;
  156.  
  157.     if (gethostname(hostname, 100) < 0) {
  158.         perror("gethostname");
  159.         exit(1);
  160.     }
  161.  
  162.     hostentPtr = gethostbyname(hostname);
  163.     if (hostentPtr == (struct hostent *)NULL) {
  164.         perror("gethostbyname");
  165.         exit(2);
  166.     }
  167.     myAddr = *(struct in_addr *)hostentPtr->h_addr_list[0];
  168.     {
  169.         unsigned char *addrPtr;
  170.  
  171.         addrPtr = (unsigned char *)&myAddr;
  172.         log("My name and addr: %s %d:%d:%d:%d\n", hostname,
  173.                 addrPtr[0], addrPtr[1], addrPtr[2], addrPtr[3]);
  174.     }
  175.  
  176.     for (argc--, argv++ ; argc > 0 ; argc--, argv++) {
  177.         if (argv[0][0] == '-') {
  178.             switch (argv[0][1]) {
  179.             case 'd':
  180.                 debug++;
  181.                 break;
  182.             }
  183.         }
  184.     }
  185.     
  186.     if (debug == 0) {
  187.         int t;
  188.         if (fork())
  189.             exit(0);
  190.         for (f = 0; f < 10; f++)
  191.             (void) close(f);
  192.         (void) open("/", 0);
  193.         (void) dup2(0, 1);
  194.         (void) dup2(0, 2);
  195.         t = open("/dev/tty", 2);    
  196.         if (t >= 0) {
  197.             ioctl(t, TIOCNOTTY, (char *)0);
  198.             (void) close(t);
  199.         }
  200.     }
  201.  
  202.     log("BOOTP server starting up.");
  203.  
  204. reopenSocket:
  205.  
  206.     while ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  207.         log("socket call failed");
  208.         sleep(5);
  209.     }
  210. #ifdef notdef
  211.     ifconf.ifc_len = sizeof ifreq;
  212.     ifconf.ifc_req = ifreq;
  213.     if (ioctl(s, SIOCGIFCONF, (caddr_t)&ifconf) < 0
  214.         || ifconf.ifc_len <= 0) {
  215.         log("'get interface config' ioctl failed");
  216.         exit(1);
  217.     }
  218. #endif
  219.     sin.sin_port = htons(IPPORT_BOOTPS);
  220.     while (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
  221.         perror("bind");
  222.         log("bind call failed");
  223.         sleep(5);
  224.     }
  225.     for (;;) {
  226.         fromlen = sizeof (from);
  227.         n = recvfrom(s, buf, sizeof buf, 0, (caddr_t)&from, &fromlen);
  228.         if (n <= 0) {
  229.             log("recvfrom failed: %s\n", strerror(errno));
  230.             if (errno==ESTALE || errno==EIO) {
  231.             close(s);
  232.             log("restarting socket");
  233.             goto reopenSocket;
  234.             }
  235.             sleep(10);
  236.             continue;
  237.         }
  238.         bp = (struct bootp *) buf;
  239.         if (n < sizeof *bp) {
  240.             continue;
  241.         }
  242.         readtab();    /* (re)read bootptab */
  243.         switch (bp->bp_op) {
  244.         case BOOTREQUEST:
  245.             request();
  246.             break;
  247.  
  248.         case BOOTREPLY:
  249.             reply();
  250.             break;
  251.         }
  252.     }
  253. }
  254.  
  255.  
  256. /*
  257.  * Process BOOTREQUEST packet.
  258.  *
  259.  * (Note, this version of the bootp.c server never forwards 
  260.  * the request to another server.  In our environment the 
  261.  * stand-alone gateways perform that function.)
  262.  *
  263.  * (Also this version does not interpret the hostname field of
  264.  * the request packet;  it COULD do a name->address lookup and
  265.  * forward the request there.)
  266.  */
  267. static void
  268. request()
  269. {
  270.     register struct bootp *rq = (struct bootp *)buf;
  271.     struct bootp rp;
  272.     char *strPtr;
  273.     char path[64], file[64];
  274.     register struct hosts *hp;
  275.     register n;
  276.  
  277.     rp = *rq;    /* copy request into reply */
  278.     rp.bp_op = BOOTREPLY;
  279.     if (rq->bp_ciaddr.s_addr == 0) { 
  280.         /*
  281.          * client doesnt know his IP address, 
  282.          * search by hardware address.
  283.          */
  284.         for (hp = &hosts[0], n = 0 ; n < nhosts ; n++,hp++)
  285.             if (rq->bp_htype == hp->htype
  286.                && bcmp(rq->bp_chaddr, hp->haddr, 6) == 0)
  287.                 break;
  288.         if (n == nhosts)
  289.             return;    /* not found */
  290.         rp.bp_yiaddr = hp->iaddr;
  291.     } else {
  292.         /* search by IP address */
  293.         for (hp = &hosts[0], n = 0 ; n < nhosts ; n++,hp++)
  294.             if (rq->bp_ciaddr.s_addr == hp->iaddr.s_addr)
  295.                 break;
  296.         if (n == nhosts)
  297.             return;
  298.     }
  299.     if (strcmp(rq->bp_file, "sunboot14") == 0)
  300.         rq->bp_file[0] = 0;    /* pretend it's null */
  301.     strPtr = strchr(rq->bp_file,' ');
  302.     if (strPtr != (char *)NULL) {
  303.         *strPtr = 0;
  304.     }
  305.     log("request from %s for '%s'", hp->host, rq->bp_file);
  306.     strcpy(path, homedir);
  307.     strcat(path, "/");
  308.     strcat(path, hp->bootfile);
  309.     strcat(path, ".md/");
  310.     if (rq->bp_file[0] == 0) { /* if client didnt specify file */
  311.         if (hp->bootfile[0] == 0)
  312.             strcpy(file, defaultboot);
  313.         else
  314.             strcpy(file, hp->bootfile);
  315.     } else {
  316.         /* client did specify file */
  317.  
  318.         /*
  319.          * For now the ds5000 always returns an extra '/' at the beginning
  320.          * of the path name. 
  321.          */
  322.          if (!strcmp(hp->bootfile, "ds5000")) {
  323.          strcpy(file, &rq->bp_file[1]);
  324.          } else {
  325.         strcpy(file, rq->bp_file);
  326.          }
  327.     }
  328.     if (file[0] == '/')    /* if absolute pathname */
  329.         strcpy(path, file);
  330.     else
  331.         strcat(path, file);
  332.     /* try first to find the file with a ".host" suffix */
  333.     n = strlen(path);
  334.     strcat(path, ".");
  335.     strcat(path, hp->host);
  336.     if (access(path, R_OK) < 0) {
  337.         path[n] = 0;    /* try it without the suffix */
  338.         if (access(path, R_OK) < 0) {
  339.             if (rq->bp_file[0])  /* client wanted specific file */
  340.                 return;        /* and we didnt have it */
  341.             log("boot file %s* missing?", path);
  342.         }
  343.     }
  344.     log("replyfile %s", path);
  345.     strcpy(rp.bp_file, path);
  346.     sendreply(&rp, 0);
  347.     return;
  348. }
  349.  
  350.  
  351. /*
  352.  * Process BOOTREPLY packet (something is using us as a gateway).
  353.  */
  354. static void
  355. reply()
  356. {
  357.     struct bootp *bp = (struct bootp *)buf;
  358.  
  359.     sendreply(bp, 1);
  360.     return;
  361. }
  362.  
  363.  
  364. /*
  365.  * Send a reply packet to the client.  'forward' flag is set if we are
  366.  * not the originator of this reply packet.
  367.  */
  368. static void
  369. sendreply(bp, forward)
  370.     register struct bootp *bp;
  371. {
  372.     iaddr_t dst;
  373.     struct sockaddr_in to;
  374.  
  375.     to = sin;
  376.     to.sin_port = htons(IPPORT_BOOTPC);
  377.     /*
  378.      * If the client IP address is specified, use that
  379.      * else if gateway IP address is specified, use that
  380.      * else make a temporary arp cache entry for the client's NEW 
  381.      * IP/hardware address and use that.
  382.      */
  383.     if (bp->bp_ciaddr.s_addr) {
  384.         dst = bp->bp_ciaddr;
  385.         if (debug) log("reply ciaddr");
  386.     } else if (bp->bp_giaddr.s_addr && forward == 0) {
  387.         dst = bp->bp_giaddr;
  388.         to.sin_port = htons(IPPORT_BOOTPS);
  389.         if (debug) log("reply giaddr");
  390.     } else {
  391.         dst = bp->bp_yiaddr;
  392.         if (debug) log("reply yiaddr %x", dst.s_addr);
  393.         setarp(&dst, bp->bp_chaddr, bp->bp_hlen);
  394.     }
  395.  
  396.     if (forward == 0) {
  397.         /*
  398.          * If we are originating this reply, we
  399.          * need to find our own interface address to
  400.          * put in the bp_siaddr field of the reply.
  401.          * If this server is multi-homed, pick the
  402.          * 'best' interface (the one on the same net
  403.          * as the client).
  404.          */
  405.         int maxmatch = 0;
  406.         int len, m;
  407.         register struct ifreq *ifrp, *ifrmax;
  408.  
  409. #ifdef notdef
  410.         ifrmax = ifrp = &ifreq[0];
  411.         len = ifconf.ifc_len;
  412.         for ( ; len > 0 ; len -= sizeof ifreq[0], ifrp++) {
  413.             if ((m = nmatch((caddr_t)&dst,
  414.                 (caddr_t)&((struct sockaddr_in *)
  415.                  (&ifrp->ifr_addr))->sin_addr)) > maxmatch) {
  416.                 maxmatch = m;
  417.                 ifrmax = ifrp;
  418.             }
  419.         }
  420.         if (bp->bp_giaddr.s_addr == 0) {
  421.             if (maxmatch == 0) {
  422.                 log("missing gateway address");
  423.                 return;
  424.             }
  425.             bp->bp_giaddr = ((struct sockaddr_in *)
  426.                 (&ifrmax->ifr_addr))->sin_addr;
  427.         }
  428. #endif
  429.         bp->bp_siaddr = myAddr;
  430.     }
  431.     to.sin_addr = dst;
  432.     if (sendto(s, (caddr_t)bp, sizeof *bp, 0, &to, sizeof to) < 0)
  433.         log("send failed");
  434.     return;
  435. }
  436.  
  437.  
  438. /*
  439.  * Return the number of leading bytes matching in the
  440.  * internet addresses supplied.
  441.  */
  442. static int
  443. nmatch(ca,cb)
  444.     register char *ca, *cb;
  445. {
  446.     register n,m;
  447.  
  448.     for (m = n = 0 ; n < 4 ; n++) {
  449.         if (*ca++ != *cb++)
  450.             return(m);
  451.         m++;
  452.     }
  453.     return(m);
  454. }
  455.  
  456.  
  457. /*
  458.  * Setup the arp cache so that IP address 'ia' will be temporarily
  459.  * bound to hardware address 'ha' of length 'len'.
  460.  */
  461. static void
  462. setarp(ia, ha, len)
  463.     iaddr_t *ia;
  464.     u_char *ha;
  465. {
  466. #ifdef notdef
  467.     struct sockaddr_in *si;
  468.  
  469.     arpreq.arp_pa.sa_family = AF_INET;
  470.     si = (struct sockaddr_in *)&arpreq.arp_pa;
  471.     si->sin_addr = *ia;
  472.     bcopy(ha, arpreq.arp_ha.sa_data, len);
  473.     if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0)
  474.         log("set arp ioctl failed");
  475. #endif
  476.     return;
  477. }
  478.  
  479. static void
  480. readtab()
  481. {
  482.     struct stat st;
  483.     register char *cp;
  484.     int v;
  485.     register i;
  486.     char temp[64], tempcpy[64];
  487.     register struct hosts *hp;
  488.     char spriteID[8];
  489.     char netType[20];
  490.  
  491.     if (fp == NULL) {
  492.     if ((fp = fopen(bootptab, "r")) == NULL) {
  493.             log("can't open %s", bootptab);
  494.         exit(1);
  495.     }
  496.     }
  497.     fstat(fileno(fp), &st);
  498.     if (st.st_mtime == modtime && st.st_nlink) {
  499.     return;    /* hasnt been modified or deleted yet */
  500.     }
  501.     fclose(fp);
  502.     if ((fp = fopen(bootptab, "r")) == NULL) {
  503.     log("can't open %s", bootptab);
  504.     exit(1);
  505.     }
  506.     fstat(fileno(fp), &st);
  507.     log("(re)reading %s", bootptab);
  508.     modtime = st.st_mtime;
  509.     nhosts = 0;
  510.     hp = &hosts[0];
  511.     linenum = 0;
  512.  
  513.     /*
  514.      * read and parse each line in the file.
  515.      */
  516.     for (;;) {
  517.     if (fgets(line, sizeof line, fp) == NULL) {
  518.         break;    /* done */
  519.     }
  520.     if ((i = strlen(line))) {
  521.         line[i-1] = 0;    /* remove trailing newline */
  522.     }
  523.     linep = line;
  524.     linenum++;
  525.     /* skip leading whitespace */
  526.     while (isspace(*linep)) {
  527.         ++linep;
  528.     }
  529.     if (*linep == '#' || *linep == '\0') {
  530.         continue;    /* skip comment lines */
  531.     }
  532.     /* fill in host table */
  533.     /* get spriteid */
  534.     getfield(spriteID, sizeof(spriteID));
  535.     if (!isdigit(*spriteID)) {
  536.         log("bad sprite ID at line %d of %s", linenum, bootptab);
  537.         exit(1);
  538.     }
  539.     getfield(netType, sizeof(netType));
  540.     if (debug && strcmp(netType, "ether") && strcmp(netType, "inet")) {
  541.         log("unrecognized network type: %s, line %d, %s\n",
  542.         netType, linenum, bootptab);
  543.     }
  544.     hp->htype = 1;
  545.     getfield(temp, sizeof temp);
  546.     strcpy(tempcpy, temp);
  547.     cp = tempcpy;
  548.     /* parse hardware address */
  549.     for (i = 0 ; i < sizeof hp->haddr ; i++) {
  550.         char *cpold;
  551.         char c;
  552.         cpold = cp;
  553.         while (*cp != '.' && *cp != ':' && *cp != 0) {
  554.         cp++;
  555.         }
  556.         c = *cp;    /* save original terminator */
  557.         *cp = 0;
  558.         cp++;
  559.         if (sscanf(cpold, "%x", &v) != 1) {
  560.         goto badhex;
  561.         }
  562.         hp->haddr[i] = v;
  563.         if (c == 0) {
  564.         break;
  565.         }
  566.     }
  567.     if (i != 5) {
  568. badhex:     log("bad hex address: %s, at line %d of bootptab", temp, linenum);
  569.             continue;
  570.     }
  571.     getfield(temp, sizeof temp);
  572.     if ((i = inet_addr(temp)) == -1 || i == 0) {
  573.         log("bad internet address: %s, at line %d of bootptab",
  574.         temp, linenum);
  575.         continue;
  576.     }
  577.     hp->iaddr.s_addr = i;
  578.     getfield(hp->bootfile, sizeof hp->bootfile);
  579.     if (debug &&
  580.         strcmp(hp->bootfile, "ds3100") && strcmp(hp->bootfile, "sun3") &&
  581.         strcmp(hp->bootfile, "sun4") && strcmp(hp->bootfile, "sun4c") &&
  582.         strcmp(hp->bootfile, "spur") && strcmp(hp->bootfile, "ds5000")) {
  583.           log("unrecognized machine type: %s, line %d, %s\n",
  584.           hp->bootfile, linenum, bootptab);
  585.     }
  586.     if ((strcmp(hp->bootfile, "ds3100") != 0) &&
  587.         (strcmp(hp->bootfile, "ds5000") != 0)) {
  588.         /* bootp is only used for decStations */
  589.         continue;
  590.     }
  591.     getfield(hp->host, sizeof hp->host);
  592.     if (++nhosts >= MHOSTS) {
  593.         log("'hosts' table length exceeded");
  594.         exit(1);
  595.     }
  596.     hp++;
  597.     }
  598.     return;
  599. }
  600.  
  601.  
  602. /*
  603.  * Get next field from 'line' buffer into 'str'.  'linep' is the 
  604.  * pointer to current position.
  605.  */
  606. static void
  607. getfield(str, len)
  608.     char *str;
  609. {
  610.     register char *cp = str;
  611.  
  612.     for (; *linep && (*linep == ' ' || *linep == '\t') ; linep++) {
  613.     continue;   /* skip spaces/tabs */
  614.     }
  615.     if (*linep == '\0') {
  616.     *cp = '\0';
  617.     return;
  618.     }
  619.     len--;  /* save a spot for a null */
  620.     for (; *linep && *linep != ' ' & *linep != '\t' ; linep++) {
  621.     *cp++ = *linep;
  622.     if (--len <= 0) {
  623.         *cp = '\0';
  624.         log("string truncated: %s, on line %d of bootptab",    str, linenum);
  625.         return;
  626.     }
  627.     }
  628.     *cp = '\0';
  629.     return;
  630. }
  631.  
  632. #if 0
  633. /*
  634.  * Read bootptab database file.  Avoid rereading the file if the
  635.  * write date hasnt changed since the last time we read it.
  636.  */
  637. static void
  638. readtab()
  639. {
  640.     struct stat st;
  641.     register char *cp;
  642.     int v;
  643.     register i;
  644.     char temp[64], tempcpy[64];
  645.     register struct hosts *hp;
  646.     int skiptopercent;
  647.  
  648.     if (fp == 0) {
  649.         if ((fp = fopen(bootptab, "r")) == NULL) {
  650.             log("can't open %s", bootptab);
  651.             exit(1);
  652.         }
  653.     }
  654.     fstat(fileno(fp), &st);
  655.     if (st.st_mtime == modtime && st.st_nlink)
  656.         return;    /* hasnt been modified or deleted yet */
  657.     fclose(fp);
  658.     if ((fp = fopen(bootptab, "r")) == NULL) {
  659.         log("can't open %s", bootptab);
  660.         exit(1);
  661.     }
  662.     fstat(fileno(fp), &st);
  663.     log("(re)reading %s", bootptab);
  664.     modtime = st.st_mtime;
  665.     homedir[0] = defaultboot[0] = 0;
  666.     nhosts = 0;
  667.     hp = &hosts[0];
  668.     linenum = 0;
  669.     skiptopercent = 1;
  670.  
  671.     /*
  672.      * read and parse each line in the file.
  673.      */
  674.     for (;;) {
  675.         if (fgets(line, sizeof line, fp) == NULL)
  676.             break;    /* done */
  677.         if ((i = strlen(line)))
  678.             line[i-1] = 0;    /* remove trailing newline */
  679.         linep = line;
  680.         linenum++;
  681.         if (line[0] == '#' || line[0] == 0 || line[0] == ' ')
  682.             continue;    /* skip comment lines */
  683.         /* fill in fixed leading fields */
  684.         if (homedir[0] == 0) {
  685.             getfield(homedir, sizeof homedir);
  686.             continue;
  687.         }
  688.         if (defaultboot[0] == 0) {
  689.             getfield(defaultboot, sizeof defaultboot);
  690.             continue;
  691.         }
  692.         if (skiptopercent) {    /* allow for future leading fields */
  693.             if (line[0] != '%')
  694.                 continue;
  695.             skiptopercent = 0;
  696.             continue;
  697.         }
  698.         /* fill in host table */
  699.         getfield(hp->host, sizeof hp->host);
  700.         getfield(temp, sizeof temp);
  701.         sscanf(temp, "%d", &v);
  702.         hp->htype = v;
  703.         getfield(temp, sizeof temp);
  704.         strcpy(tempcpy, temp);
  705.         cp = tempcpy;
  706.         /* parse hardware address */
  707.         for (i = 0 ; i < sizeof hp->haddr ; i++) {
  708.             char *cpold;
  709.             char c;
  710.             cpold = cp;
  711.             while (*cp != '.' && *cp != ':' && *cp != 0)
  712.                 cp++;
  713.             c = *cp;    /* save original terminator */
  714.             *cp = 0;
  715.             cp++;
  716.             if (sscanf(cpold, "%x", &v) != 1)
  717.                 goto badhex;
  718.             hp->haddr[i] = v;
  719.             if (c == 0)
  720.                 break;
  721.         }
  722.         if (hp->htype == 1 && i != 5) {
  723.     badhex:        log("bad hex address: %s, at line %d of bootptab",
  724.                 temp, linenum);
  725.             continue;
  726.         }
  727.         getfield(temp, sizeof temp);
  728.         if ((i = inet_addr(temp)) == -1 || i == 0) {
  729.             log("bad internet address: %s, at line %d of bootptab",
  730.                 temp, linenum);
  731.             continue;
  732.         }
  733.         hp->iaddr.s_addr = i;
  734.         getfield(hp->bootfile, sizeof hp->bootfile);
  735.         if (++nhosts >= MHOSTS) {
  736.             log("'hosts' table length exceeded");
  737.             exit(1);
  738.         }
  739.         hp++;
  740.     }
  741.     return;
  742. }
  743.  
  744.  
  745. /*
  746.  * Get next field from 'line' buffer into 'str'.  'linep' is the 
  747.  * pointer to current position.
  748.  */
  749. static void
  750. getfield(str, len)
  751.     char *str;
  752. {
  753.     register char *cp = str;
  754.  
  755.     for ( ; *linep && (*linep == ' ' || *linep == '\t') ; linep++)
  756.         ;    /* skip spaces/tabs */
  757.     if (*linep == 0) {
  758.         *cp = 0;
  759.         return;
  760.     }
  761.     len--;    /* save a spot for a null */
  762.     for ( ; *linep && *linep != ' ' & *linep != '\t' ; linep++) {
  763.         *cp++ = *linep;
  764.         if (--len <= 0) {
  765.             *cp = 0;
  766.             log("string truncated: %s, on line %d of bootptab",
  767.                 str, linenum);
  768.             return;
  769.         }
  770.     }
  771.     *cp = 0;
  772.     return;
  773. }
  774. #endif
  775.  
  776. /*
  777.  * log an error message 
  778.  *
  779.  */
  780. static void
  781. log(va_alist)
  782.     va_dcl
  783. {
  784.     FILE *fp;
  785.     char *format;
  786.     va_list args;
  787.     time_t now;
  788.     char *t;
  789.  
  790.     va_start(args);
  791.     time(&now);
  792.     t = asctime(localtime(&now));
  793.     /* remove the newline */
  794.     t[24] = '\0';
  795.     if ((fp = fopen(bootplog, "a+")) == NULL)
  796.         return;
  797.     fprintf(fp, "[%s]: ", t);
  798.     format = va_arg(args, char *);
  799.     vfprintf(fp, format, args);
  800.     putc('\n', fp);
  801.     fclose(fp);
  802.     return;
  803. }
  804. @
  805.  
  806.  
  807. 1.6
  808. log
  809. @Added logging to record if socket is restarted.
  810. @
  811. text
  812. @d60 1
  813. a60 1
  814. static char    *bootplog = "/usr/adm/bootplog";
  815. d68 1
  816. a68 1
  817. static char    homedir[] = "/sprite/boot/ds3100.md";
  818. d255 2
  819. d264 8
  820. d273 1
  821. d529 1
  822. a529 1
  823.         strcmp(hp->bootfile, "spur")) {
  824. d533 2
  825. a534 1
  826.     if (strcmp(hp->bootfile, "ds3100") != 0) {
  827. @
  828.  
  829.  
  830. 1.5
  831. log
  832. @Fixed error handling.
  833. @
  834. text
  835. @d151 2
  836. d177 5
  837. @
  838.  
  839.  
  840. 1.4
  841. log
  842. @Changed bootp to truncate request string at first space.  This is becuase
  843. the ds3100 gives bootp the args, which bootp should ignore.
  844. @
  845. text
  846. @d110 1
  847. a110 1
  848.     if (hostentPtr == (struct hostent *)-1) {
  849. d112 1
  850. @
  851.  
  852.  
  853. 1.3
  854. log
  855. @Changed to use /etc/spritehosts instead of /etc/bootptab.
  856. @
  857. text
  858. @d50 1
  859. a50 1
  860. static long    time();            /* time of day */
  861. d211 1
  862. d240 4
  863. @
  864.  
  865.  
  866. 1.2
  867. log
  868. @*** empty log message ***
  869. @
  870. text
  871. @d1 5
  872. a21 1
  873.  
  874. d41 1
  875. d43 1
  876. a43 2
  877.  
  878. int    debug;
  879. d45 9
  880. a53 9
  881. struct    sockaddr_in sin = { AF_INET };
  882. int    s;        /* socket fd */
  883. struct    sockaddr_in from;
  884. int    fromlen;
  885. u_char    buf[1024];    /* receive packet buffer */
  886. long    time(), tloc;    /* time of day */
  887. struct    ifreq ifreq[10]; /* holds interface configuration */
  888. struct    ifconf ifconf;    /* int. config. ioctl block (points to ifreq) */
  889. struct    arpreq arpreq;    /* arp request ioctl block */
  890. d59 11
  891. a69 9
  892. char    *bootptab = "/etc/bootptab";
  893. char    *bootplog = "/usr/adm/bootplog";
  894. FILE    *fp;
  895. int    f;
  896. char    line[256];    /* line buffer for reading bootptab */
  897. char    *linep;        /* pointer to 'line' */
  898. int    linenum;    /* current ilne number in bootptab */
  899. char    homedir[64];    /* bootfile homedirectory */
  900. char    defaultboot[64]; /* default file to boot */
  901. d73 1
  902. a73 1
  903. struct hosts {
  904. d81 4
  905. a84 2
  906. int    nhosts;        /* current number of hosts */
  907. long    modtime;    /* last modification time of bootptab */
  908. d86 8
  909. a93 1
  910. struct in_addr myAddr;
  911. d95 1
  912. d148 1
  913. a148 2
  914.     time(&tloc);
  915.     log("#\n#    BOOTP server starting at %s#", ctime(&tloc));
  916. d172 7
  917. a178 1
  918.         if (n <= 0)
  919. d180 1
  920. a180 3
  921.         bp = (struct bootp *)buf;
  922.         if (n < sizeof *bp)
  923.             continue;
  924. d206 1
  925. d270 1
  926. d277 1
  927. d283 1
  928. d291 1
  929. d357 1
  930. d365 1
  931. d384 1
  932. d399 122
  933. d525 31
  934. d559 1
  935. d663 1
  936. d671 1
  937. d694 1
  938. d696 1
  939. a696 1
  940.  
  941. d702 1
  942. d709 2
  943. d713 4
  944. d719 1
  945. d724 1
  946. @
  947.  
  948.  
  949. 1.1
  950. log
  951. @Initial revision
  952. @
  953. text
  954. @d36 1
  955. d78 1
  956. a79 1
  957.  
  958. d85 20
  959. d139 1
  960. d147 1
  961. d150 1
  962. d308 1
  963. d327 2
  964. a328 2
  965.         bp->bp_siaddr = ((struct sockaddr_in *)
  966.             (&ifrmax->ifr_addr))->sin_addr;
  967. d362 1
  968. d371 1
  969. d518 2
  970. a519 2
  971. log(fmt, args)
  972. char *fmt;
  973. d522 2
  974. d525 1
  975. d528 2
  976. a529 1
  977.     vfprintf(fp, fmt, &args);
  978. @
  979.